ci(test): temporarily raise Test Core (N/6) timeout-minutes 30 -> 45, with its revert condition inline - #16451
Merged
Conversation
Shard 5/6 keeps hitting the 30-minute wall, so every tail observation is a reading of the wall rather than of the shard: the true duration is censored and unbounded above. Raising the backstop both unblocks the job and un-censors the durations the shard rebalance needs before it can be derived. The new value carries its revert condition inline, next to the value. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
huangyiirene
marked this pull request as ready for review
September 7, 2026 02:12
huangyiirene
enabled auto-merge
September 7, 2026 02:12
huangyiirene
deleted the
claude/issue-16445-raise-test-core-shard-wall
branch
September 7, 2026 03:28
This was referenced Sep 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #16445
One line moves, plus the expiry that keeps it temporary rather than permanent by forgetting. In
.github/workflows/ci.yml, thetestjob —name: Test Core (${{ matrix.shard }}/6)— goestimeout-minutes: 30→45.This executes the maintainer directive recorded on the card, verbatim: 「临时抬墙」. It is not a design proposal.
What moved — and the proof that nothing else did
The raised value now sits at line 316; it was at line 295 on the base commit
bf45e62ce, and the 21 comment lines added above it account for the whole shift. Because line numbers drift, the census below is keyed on the job, so a second changed value could not hide behind the offset.filtertesttest-gatetemporal-conformancedogfooddogfood-verifydogfood-gatebuild-corebuild-docsconsole-pinTen occurrences before, ten after — nothing added, nothing removed. Diffing the two
job valuecensuses yields exactly one changed line:The whole diff is
1 file changed, 22 insertions(+), 1 deletion(-): one value line and twenty-one comment lines, in one file.scripts/test-shard-timings.jsonis untouched, the shard count and matrix are untouched, novitestconfig is touched, no test is skipped or quarantined, and no cancelled shard was re-run — those were different options and none of them was the one chosen.Why 45, and why it is an instrument as well as an unblock
Test Core (5/6)has been killed at the 30-minute wall repeatedly today — 12+ observations at 30:16 ×7 · 30:17 ×2 · 30:18 ×2 · 30:21, with every other job in every one of those runs green.Those are not measurements of the shard. They are readings of
timeout-minutes: the true duration is>= 30:16, censored and unbounded above. The only uncensored shard-5 readings are 25:32 and 27:36, and shard 6/6 — never killed — has been seen at 28:56. So the observed green band is 25:30–28:56 against a 30:00 wall: roughly a minute of margin at the top.45 is not arbitrary. The same file already runs
console-pinattimeout-minutes: 45, so it is a value this repo already tolerates on a required job, and it is approached from below rather than exceeded.The second effect is the more valuable one: while the wall stands at 30, the shard timings cannot be re-derived from CI history, because every tail observation is censored. Raising it produces the real durations, which is precisely the input the shard rebalance needs before anyone edits
scripts/test-shard-timings.json. That rebalance is not addressed here and #16173 remains open.The revert condition lives in the file, not only in this PR
A temporary raise with no expiry written beside it becomes permanent by forgetting. The new value therefore carries an inline block that names #16173 as the reason, states plainly that the raise is temporary, and states the revert condition explicitly: back to
30once #16173 lands its shard rebalance.The pre-existing rationale paragraph above the value is left byte-for-byte intact — it argues for 30, and it is exactly the argument the revert must satisfy — but it would otherwise read as a description of the current value, so the new block says in so many words that the paragraph above describes the value this line must return to, not the value it currently carries. The stall guard on the test steps remains the primary hang detector throughout; this backstop is loose only for that window.
Governed surface: NO — measured from the guard, not assumed from prose
Read from the guard's own source rather than from the AGENTS.md list.
scripts/pm/check-governed-queue-guard.mjsstates no surface list of its own — it importsGOVERNED_SURFACESfromscripts/pm/check-governed-merges.mjs, and its--self-testpins that with the casethis-file-restates-no-surface-list. Running the register and the seat-side pre-arm predicate against this PR's final file list:Today's register is
docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md, printed from the module rather than recalled..github/workflows/**is not among them, and a control path.claude/x.mdrun through the same predicate does hit, so the negative reading is not a broken matcher answering "no" to everything. TheGoverned Surface Queue Guardcheck on this PR has since concluded success, which is the guard itself agreeing on this PR's own file list.⇒ This PR takes the ordinary merge-queue path. It is left as a draft for the PM regardless; flipping it ready and enqueueing is the PM's call, not this seat's.
Clause ②: no — confirmed, not inherited
Confirmed independently of the claim comment's declaration. The diff changes a CI job's wall-clock backstop. It touches nothing under
packages/spec/src/**, no*.zod.tscontract schema, no error-code ledger, no export, and no accept-set: no published contract accepts or rejects anything differently after this PR, and no public surface widens. Clause ② is about the published contract surface, so it reads no.Changeset: not owed —
skip-changesetNothing in this diff publishes. The change set is one workflow file; no package's published surface moves, so there is no released package for a changeset to describe, and a
patchentry here would announce a release that does not exist. That is the textbook case the label exists for, and the label is a real mechanism in this repo —changeset-checkin.github/workflows/pr-automation.ymlis exempted by the job-levelif:plus its two live label re-reads, with no path-based auto-exemption to fall back on. The label is applied to this PR as an authoring step rather than left to CI, and theCheck Changesetrun on this PR concluded success.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 38 families for this change set, and--ranreconciles clean:36 green, exit 0. Two returned exit 3,
PREREQUISITE NOT MET— reported as NOT MEASURED, never as green and never as red:pnpm check:dts-closure— "Not one of the 79 workspace package(s) under.has adist/". Its own text: "This is NOT a pass and NOT a finding."pnpm check:dual-build-cjs-loads— "this gate reads built output, and some package has nodist/. Nothing was measured."Both read
dist/, and this diff changes no package source, so a closure build would have them measure something no path here can move. CI builds the closure and runs them.The two load-bearing families for this specific change both genuinely read the raised value rather than skipping:
The
budget 45mis this PR's value being read back, and the slack on the guarded step goes 10m → 25m.pnpm check:stall-guard-headroomis green but runs--self-testonly, so it grades the checker's fixtures, not this diff; it is not PR clearance in either direction.pnpm check:required-contexts,pnpm check:shard-attestation,pnpm check:ci-filter-parityandpnpm check:nul-bytesare green on the real diff.The file also parses:
yaml.safe_loadreturnsjobs.test['timeout-minutes'] == 45as anint, with the matrix stillshard: [1, 2, 3, 4, 5, 6]and 10 jobs.The self-test fired — and its answer is "not from this PR"
This PR's own CI run executes with the raised wall, and all six
Test Coreshards went green. But their durations are not shard measurements, and reporting them as such would be a phantom reading of exactly the kind this card is about.Test Core (5/6)completed in 54s (02:05:18Z → 02:06:12Z), and its own log says why:A
.github/workflows/**-only diff affects zero packages, so the partitioner scheduled zero items onto every shard. That 54s is fixed per-shard overhead — checkout, pnpm/Turbo cache restore, install, attestation — and nothing else.⇒ This PR un-censors nothing, and the shard-timing work should not read a number from it. The raise is still the instrument, but it only reads on a PR whose diff actually schedules packages onto shard 5. The first uncensored shard-5 duration will come from the next such PR to run against this workflow — that is where the rebalance should take its input, and it is the reason this raise wants to stay in place until then.